home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / ear / uniq.lha / uniq.c < prev    next >
C/C++ Source or Header  |  1994-06-11  |  12KB  |  439 lines

  1. /*
  2.  * Name:        uniq.c
  3.  * Author:        Oliver Kaufmann
  4.  * 
  5.  * created:        ?
  6.  * last modified:    10.6.1994
  7.  * Version:        $VER: uniq 1.1
  8.  * 
  9.  * Doc:            uniq.doc
  10.  * 
  11.  */
  12.  
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <dos/dos.h>
  16. #include <functions.h>
  17. #include <string.h>
  18.  
  19. void CloseAll(char *s);
  20. char *makename(char *s, int blen, int elen, char **tb, char **tex, char *buffer);
  21. char *modifyname(char *tb, int blen, int elen, long sernum, int origlen);
  22. char *savestring(char *s);
  23. struct tbl *feedtbl(char *s, struct tbl *firsttbl, int type);
  24. struct tbl *lookup(char *t, struct tbl *firsttbl, struct tbl *excludetbl);
  25. struct tbl *modifytbl(char *s, char *t, struct tbl *thistbl);
  26. struct tbl *inserttbl(char *s, char *t, int type,  struct tbl *firsttbl);
  27. struct tbl *uniq(struct tbl *thistbl, struct tbl *firsttbl,int blen, int elen);
  28. struct tbl *makeuniq(struct tbl *firsttbl, int blen, int elen);
  29. void uniqthislevel(struct tbl *thisdir, char *origpathname, char *newpathname);
  30. void giveout(struct tbl *firsttbl, char *lformat, int allflag, int quoteflag);
  31. struct tbl *freetbl(struct tbl *thistbl);
  32.  
  33.  
  34. char ver[] = "$VER: uniq 1.1 (10.6.1994) © by Oliver Kaufmann";
  35. char *usage = "uniq [<options>]\n\
  36.           -d[<dir>] : use contents of <dir> as input, otherwise use stdin\n\
  37.                  -a : print all names, even those which do not change\n\
  38.                  -f : process files only, no dirs (requires -d option)\n\
  39.                  -q : enclose output in quotes (rename \"%s\" \"%s\")\n\
  40.                  -r : recurse sub-dirs (requires -d option)\n\
  41.         -l<lformat> : use <lformat> for output (default rename %s %s)\n\
  42.       -m[<mformat>] : enable & print <mformat> for dirs (default makedir %s)\n\
  43.         -p<pattern> : pattern to apply (default #?)\n\
  44.  -b<basenamelength> : max. length of the uniqified string (default 8)\n\
  45. -e<extensionlength> : max. length of the uniqified extension (default 3)";
  46.  
  47.  
  48. struct tbl {
  49.     char *orig;
  50.     char *new;
  51.     int type;
  52.     struct tbl *nexttbl;
  53. };
  54.  
  55. struct MyAnchorPath {
  56.     struct AChain    *ap_Base;    /* pointer to first anchor */
  57.     struct AChain    *ap_Last;    /* pointer to last anchor */
  58.     LONG    ap_BreakBits;        /* Bits we want to break on */
  59.     LONG    ap_FoundBreak;        /* Bits we broke on. Also returns ERROR_BREAK */
  60.     BYTE    ap_Flags;        /* New use for extra word. */
  61.     BYTE    ap_Reserved;
  62.     WORD    ap_Strlen;        /* This is what ap_Length used to be */
  63.     struct    FileInfoBlock ap_Info;
  64.     UBYTE    ap_Buf[1];        /* Buffer for path name, allocated by user */
  65. };
  66.  
  67.  
  68. #define BUFLEN 256
  69. char pbuf[BUFLEN];
  70. char str1[BUFLEN];
  71. char str2[BUFLEN];
  72.  
  73. int level = 0;
  74. int quoteflag = 0;
  75. int mformflag = 0;
  76. int allfilendirs = 1;
  77. int allflag  = 0;
  78. int recursflag = 0;
  79. int blen=8;
  80. int elen=3;
  81. char *lformat = "rename %s %s";
  82. char *mformat = "makedir %s";
  83. char *pattern="#?";
  84.  
  85. void main(int argc, char *argv[])
  86. {
  87.    struct tbl localtbl;
  88.    struct tbl *firsttbl=NULL;
  89.    char lbuf[BUFLEN];
  90.    char *dirname=NULL;
  91.  
  92.    char *s, *opt;
  93.    int i, res;
  94.  
  95.    for(i=1; i<argc; i++) {
  96.        if( *(opt=argv[i]) == '-') {
  97.           switch(opt[1]) {
  98.              case 'd' : dirname = &opt[2]; break;
  99.              case 'a' : allflag      = 1 ; break;
  100.              case 'r' : recursflag   = 1 ; break;
  101.              case 'q' : quoteflag    = 1 ; break;
  102.              case 'f' : allfilendirs = 0 ; break;
  103.              case 'l' : lformat = &opt[2]; break;
  104.              case 'p' : pattern = &opt[2]; break;
  105.              case 'm' : mformflag    = 1;
  106.                         if( opt[2] != 0 )
  107.                            mformat = &opt[2];
  108.                         break;
  109.              case 'b' : if( (blen = atoi(&opt[2]) ) <= 0)
  110.                            CloseAll("basenamelength must be > 0");
  111.                         break;
  112.              case 'e' : if( (elen = atoi(&opt[2])) < 0)
  113.                            CloseAll("extensionlength must be >= 0");
  114.                         break;
  115.              default  : printf("unknown option: ignored\n");
  116.                         break;
  117.           }
  118.        } else if( *opt == '?')
  119.           CloseAll(usage);
  120.    }
  121.  
  122.    if(dirname != NULL) {
  123.       localtbl.orig = dirname;
  124.       localtbl.new = "";
  125.       localtbl.nexttbl = NULL;
  126.       uniqthislevel(&localtbl,dirname,"");
  127.    } else {
  128.       if( ParsePattern(pattern, pbuf, BUFLEN) == -1)
  129.          CloseAll("pattern too long");
  130.       while( (res=scanf("%s",lbuf)) != EOF) {
  131.          if(res==0)
  132.             CloseAll("res = 0");
  133.          if(MatchPattern(pbuf, lbuf))                      /* nur wenn pattern matched */
  134.             firsttbl = feedtbl(lbuf, firsttbl, 0);
  135.       }
  136.       if(firsttbl != NULL)
  137.          if( (firsttbl=makeuniq(firsttbl, blen, elen)) == NULL)
  138.             CloseAll("unable to uniqify filetbl");
  139.       giveout(firsttbl, lformat, allflag, quoteflag);
  140.    }
  141.  
  142.    CloseAll(NULL);
  143. }
  144.  
  145. #define PATHNAMELEN 256
  146. void uniqthislevel(struct tbl *thisdir, char *origpathname, char *newpathname)
  147. {
  148.    struct FileInfoBlock *fib;
  149.    struct AnchorPath *ap;
  150.    int result, emptyflag = 1;
  151.    char origpath[PATHNAMELEN];               /* store full orig path */
  152.    char newpath[PATHNAMELEN];                /* store full new  path */
  153.    struct tbl *looptbl=NULL;
  154.    struct tbl *firsttbl=NULL;
  155.    BPTR lock, oldlock;
  156.  
  157.    if(thisdir == NULL) {
  158.       return;
  159.    }
  160.  
  161.    level += 1;
  162.  
  163.    if( (ap=(struct AnchorPath *)malloc(sizeof(struct MyAnchorPath)) ) == NULL)
  164.       CloseAll("no memory for MyAnchorPath");
  165.  
  166.    memset(ap,0,sizeof(struct MyAnchorPath)-1);              /* crucial ! struct must be 0ed */
  167.                                                             /* took me 2 h to find out */
  168.    if( (lock=Lock(thisdir->orig,ACCESS_READ)) == 0)
  169.        CloseAll("no lock on dir");
  170.    oldlock = CurrentDir(lock);
  171.    
  172.    ap->ap_Strlen = 0;
  173.    ap->ap_BreakBits = 0;
  174.    ap->ap_FoundBreak = 0;
  175.  
  176.    result = MatchFirst(pattern, ap);                        /* pattern global ! */
  177.    if ( result == 0 ) {
  178.       do { 
  179.          emptyflag = 0;
  180.          fib = &ap->ap_Info;
  181.          firsttbl = feedtbl(fib->fib_FileName, firsttbl, fib->fib_DirEntryType);
  182.       } while ( !(result = MatchNext(ap)) );
  183.    }
  184.  
  185.    if(result != ERROR_NO_MORE_ENTRIES)
  186.       CloseAll("MatchFirst: other error");
  187.  
  188.     MatchEnd(ap);
  189.     free(ap); 
  190.  
  191.    if(firsttbl != NULL) {
  192.       if( (firsttbl=makeuniq(firsttbl, blen, elen)) == NULL)
  193.          CloseAll("unable to uniqify filetbl");
  194.    }
  195.  
  196.    looptbl = firsttbl;
  197.    while (looptbl != NULL) {
  198.       strcpy(origpath,origpathname);
  199.       if( !AddPart(origpath, looptbl->orig, PATHNAMELEN) )
  200.          CloseAll("path to long");
  201.       strcpy(newpath, newpathname);
  202.       if( !AddPart(newpath, looptbl->new, PATHNAMELEN) )
  203.          CloseAll("path to long");
  204.  
  205.       if(mformflag && looptbl->type >= 0) {                 /* directory special output */
  206.          *str1 = 0;
  207.          if(quoteflag) strcat(str1,"\"");
  208.          strcat(str1,newpath);
  209.          if(quoteflag) strcat(str1,"\"");
  210.          printf(mformat, str1);
  211.          printf("\n");
  212.       }
  213.       if( allfilendirs || looptbl->type < 0) {              /* file output */
  214.          if( allflag || strcmp(looptbl->orig, looptbl->new) ) {
  215.             *str1 = 0;
  216.             if(quoteflag) strcat(str1,"\"");
  217.             strcat(str1,origpath);
  218.             if(quoteflag) strcat(str1,"\"");
  219.             *str2 = 0;
  220.             if(quoteflag) strcat(str2,"\"");
  221.             strcat(str2,newpath);
  222.             if(quoteflag) strcat(str2,"\"");
  223.             printf(lformat ,str1, str2);
  224.             printf("\n");
  225.          }
  226.       }
  227.       if(recursflag && looptbl->type >= 0) {
  228.          uniqthislevel(looptbl, origpath, newpath);
  229.       }
  230.       
  231.       looptbl = looptbl->nexttbl;
  232.    }
  233.  
  234.    CurrentDir(oldlock);
  235.    UnLock(lock);
  236.    freetbl(firsttbl);                    /* free memory */
  237.    level -= 1;
  238. }
  239.  
  240.  
  241.  
  242. struct tbl *makeuniq(struct tbl *firsttbl, int blen, int elen)
  243. {
  244.    struct tbl *thistbl;
  245.  
  246.    thistbl = firsttbl;
  247.    while(thistbl != NULL) {
  248.       if( uniq(thistbl, firsttbl, blen, elen) == NULL)
  249.          return NULL;
  250.       thistbl = thistbl->nexttbl;
  251.    }
  252.    return firsttbl;
  253. }
  254.  
  255. struct tbl *uniq(struct tbl *thistbl, struct tbl *firsttbl,int blen, int elen)
  256. {
  257.    char lbuf[BUFLEN];
  258.    char buffer[BUFLEN];
  259.  
  260.    char *t, *tb, *tex;
  261.    char *s;
  262.  
  263.    long sernum;
  264.    int origlen;
  265.  
  266.    s = thistbl->orig;
  267.    makename(s, blen, elen, &tb, &tex, buffer);              /* name und extension */
  268.    origlen = strlen(tb);                                    /* base name length */
  269.  
  270.    for(sernum = 0; ; sernum++) { 
  271.       strcpy(lbuf,tb);
  272.       strcat(lbuf,tex);
  273.       if( lookup(lbuf, firsttbl, thistbl) == NULL )
  274.          break;
  275.       if( modifyname(tb, blen, elen, sernum, origlen) == 0)
  276.          return NULL;
  277.    }
  278.  
  279.    t = savestring(lbuf);
  280.  
  281.    modifytbl(s, t, thistbl);
  282.  
  283.    return thistbl;
  284. }
  285.  
  286. struct tbl *inserttbl(char *s, char *t, int type,  struct tbl *firsttbl)
  287. {
  288.    struct tbl *thistbl;
  289.  
  290.    if( (thistbl=malloc(sizeof(struct tbl))) == NULL)
  291.       CloseAll("no memory for tbl");
  292.  
  293.    thistbl->type = type;
  294.    thistbl->orig = s;
  295.    thistbl->new = t;
  296.    thistbl->nexttbl = firsttbl;
  297.    return thistbl;
  298.  
  299. }
  300.  
  301. struct tbl *modifytbl(char *s, char *t, struct tbl *thistbl)
  302. {
  303.    thistbl->orig = s;
  304.    thistbl->new = t;
  305.    return thistbl;
  306. }
  307.  
  308. struct tbl *feedtbl(char *s, struct tbl *firsttbl, int type)
  309. {
  310.    char *m;
  311.  
  312.    m = savestring(s);
  313.    return inserttbl(m, m, type, firsttbl);
  314. }
  315.  
  316. char *savestring(char *s)
  317. {
  318.    char *mem;
  319.  
  320.    if( (mem=malloc(strlen(s)+1)) == NULL)
  321.       CloseAll("no memory for string");
  322.  
  323.    strcpy(mem, s);
  324.    return mem;
  325. }
  326.  
  327. struct tbl *lookup(char *t, struct tbl *firsttbl, struct tbl *excludetbl)
  328. {
  329.    while(firsttbl != NULL) {
  330.       if( (strcmp(t, firsttbl->new) == 0) && (firsttbl != excludetbl) )
  331.          break;
  332.       firsttbl = firsttbl->nexttbl;
  333.    }
  334.    return firsttbl;
  335. }
  336.  
  337.  
  338. char *modifyname(char *tb, int blen, int elen, long sernum, int origlen)
  339. {
  340.    char lbuf[BUFLEN];
  341.    int sl, i, j, pos;
  342.  
  343.    sprintf(lbuf,"%x",sernum);
  344.    if( (sl = strlen(lbuf)) > blen )      /* sernum zu groß */
  345.       return NULL;
  346.  
  347.    pos = origlen;
  348.    if( origlen + sl > blen )
  349.       pos = blen-sl;
  350.    strncpy(tb+pos, lbuf, sl);
  351.    return tb;
  352. }
  353.  
  354. char *makename(char *s, int blen, int elen, char **tb, char **tex, char *buffer)
  355. {
  356.    char *t;
  357.    int n,m;
  358.    int sl,i;
  359.  
  360.    *tb = buffer;
  361.  
  362.    for(n=0, t=s ; (*t != '\0') && (*t != '.') ; *t++, n++);
  363.  
  364.    strncpy(buffer, s, n);             /* es wird evtl mehr kopiert */
  365.  
  366.    while(n<blen)
  367.       buffer[n++] = '\0';              /* auffüllen */
  368.  
  369.    buffer[blen] = '\0';               /* rest abschneiden */
  370.  
  371.    n = blen+1;                        /* ab hier extension */
  372.  
  373.    buffer[n] = '\0';                  /* default ist leer */
  374.  
  375.    *tex = &buffer[n];
  376.  
  377.    if(elen != 0 ) {
  378.       
  379.       for(i = sl = strlen(s)-1; sl >= 0; sl--)
  380.          if(s[sl] == '.')
  381.             break;
  382.       if(s[sl] == '.') {
  383.          buffer[n++] = '.';
  384.          strncpy(&buffer[n], &s[sl+1], i-sl+1); /* 0 mitkopieren */
  385.          n += i-sl;
  386.       }
  387.  
  388.       buffer[n] = '\0';                  /* default ist leer */
  389.       buffer[blen+elen+1+1]='\0';
  390.  
  391.    }
  392.       
  393.    return *tb;
  394.  
  395. }
  396.  
  397. void giveout(struct tbl *firsttbl, char *lformat, int allflag, int quoteflag)
  398. {
  399.    while (firsttbl != NULL) {
  400.       if( allflag || strcmp(firsttbl->orig, firsttbl->new) ) {
  401.          *str1 = 0;
  402.          if(quoteflag) strcat(str1,"\"");
  403.          strcat(str1,firsttbl->orig);
  404.          if(quoteflag) strcat(str1,"\"");
  405.          *str2 = 0;
  406.          if(quoteflag) strcat(str2,"\"");
  407.          strcat(str2,firsttbl->new);
  408.          if(quoteflag) strcat(str2,"\"");
  409.          printf(lformat, str1, str2);
  410.          printf("\n");
  411.       }
  412.       firsttbl = firsttbl->nexttbl;
  413.    }
  414. }
  415.  
  416.  
  417. struct tbl *freetbl(struct tbl *thistbl)
  418. {
  419.    struct tbl *tmptbl;
  420.    
  421.    while(thistbl != NULL) {
  422.       if(thistbl->orig != NULL)
  423.          free(thistbl->orig);
  424.       if( (thistbl->new != NULL) && (thistbl->new != thistbl->orig) )
  425.          free(thistbl->new);
  426.       tmptbl = thistbl;
  427.       thistbl = thistbl->nexttbl;
  428.       free(tmptbl);
  429.    }
  430.    return NULL;
  431. }
  432.  
  433. void CloseAll(char *s)
  434. {
  435.    if(s != NULL)
  436.       printf("%s\n",s);
  437.    exit(0);
  438. }
  439.